/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package xiaofei.library.hermes;

import xiaofei.library.hermes.bean.BaseBean;
import xiaofei.library.hermes.bean.UserManager;
import xiaofei.library.hermes.stub.StubCallback;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityConnection;
import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.bundle.ElementName;
import ohos.rpc.IRemoteObject;
import ohos.rpc.RemoteException;

/**
 * 对外提供的接口类
 *
 * @author:Hexy
 * @since 2021-03-24
 */
public final class Hermes {
    private static final String REMOTERROR = "RemoteException error";

    private Hermes() {
    }

    /**
     * 处理基础类long
     *
     * @param serviceName
     * @param ability
     * @param value1
     * @param value2
     * @param stubCallback
     */
    public static void handleLong(String serviceName, AbilitySlice ability, long value1, long value2,
                                  StubCallback stubCallback) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        ILongIDL[] proxy = new ILongIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = LongIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleLong(value1, value2);
                    if (stubCallback != null) {
                        stubCallback.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类short
     *
     * @param serviceName
     * @param ability
     * @param value1
     * @param value2
     * @param stubCallback
     */
    public static void handleShort(String serviceName, AbilitySlice ability, short value1, short value2,
                                   StubCallback stubCallback) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IShortIDL[] proxy = new IShortIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = ShortIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleShort(value1, value2);
                    if (stubCallback != null) {
                        stubCallback.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类int
     *
     * @param serviceName
     * @param ability
     * @param value1
     * @param value2
     * @param stubCallback
     */
    public static void handleInt(String serviceName, AbilitySlice ability, int value1, int value2,
                                 StubCallback stubCallback) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IIntIDL[] proxy = new IIntIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = IntIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleInt(value1, value2);
                    if (stubCallback != null) {
                        stubCallback.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类String
     *
     * @param serviceName
     * @param ability
     * @param s1
     * @param s2
     * @param stubCall
     */
    public static void handleString(String serviceName, AbilitySlice ability, String s1, String s2,
                                    StubCallback stubCall) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IStringIDL[] proxy = new IStringIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = StringIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleString(s1, s2);
                    if (stubCall != null) {
                        stubCall.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类double
     *
     * @param serviceName
     * @param ability
     * @param d1
     * @param d2
     * @param stubCall
     */
    public static void handleDouble(String serviceName, AbilitySlice ability, double d1, double d2,
                                    StubCallback stubCall) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IDoubleIDL[] proxy = new IDoubleIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = DoubleIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleDouble(d1, d2);
                    if (stubCall != null) {
                        stubCall.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类float
     *
     * @param serviceName
     * @param ability
     * @param f1
     * @param f2
     * @param stubCall
     */
    public static void handleFloat(String serviceName, AbilitySlice ability, float f1, float f2,
                                   StubCallback stubCall) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IFloatIDL[] proxy = new IFloatIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                proxy[0] = FloatIDLStub.asInterface(remote);
                try {
                    String ret = proxy[0].handleFloat(f1, f2);
                    if (stubCall != null) {
                        stubCall.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                proxy[0] = null;
            }
        });
    }

    /**
     * 处理基础类void
     *
     * @param serviceName
     * @param ability
     * @param longStub
     */
    public static void handleVoid(String serviceName, AbilitySlice ability, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IVoidIDL[] voidIdlInterface = new IVoidIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                voidIdlInterface[0] = VoidIDLStub.asInterface(remote);
                try {
                    String ret = voidIdlInterface[0].getVoid();
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                voidIdlInterface[0] = null;
            }
        });
    }

    /**
     * 处理基础类boolean
     *
     * @param serviceName
     * @param ability
     * @param isValue1
     * @param isValue2
     * @param longStub
     */
    public static void handleBoolean(String serviceName, AbilitySlice ability, boolean isValue1,
                                     boolean isValue2, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IBooleanIDL[] booleanIdl = new IBooleanIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                booleanIdl[0] = BooleanIDLStub.asInterface(remote);
                try {
                    String ret = booleanIdl[0].isBoolean(isValue1, isValue2);
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                booleanIdl[0] = null;
            }
        });
    }

    /**
     * 处理基础类byte
     *
     * @param serviceName
     * @param ability
     * @param value1
     * @param value2
     * @param longStub
     */
    public static void handleByte(String serviceName, AbilitySlice ability, byte value1,
                                  byte value2, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IByteIDL[] byteIdl = new IByteIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                byteIdl[0] = ByteIDLStub.asInterface(remote);
                try {
                    String ret = byteIdl[0].getByte(value1, value2);
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                byteIdl[0] = null;
            }
        });
    }

    /**
     * 处理Sequenceable类型
     *
     * @param serviceName
     * @param ability
     * @param value
     * @param longStub
     */
    public static void handleBean(String serviceName, AbilitySlice ability, BaseBean value, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IBaseBeanIDL[] baseBeanIdl = new IBaseBeanIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                baseBeanIdl[0] = BaseBeanIDLStub.asInterface(remote);
                try {
                    String ret = baseBeanIdl[0].handleBean(value);
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                baseBeanIdl[0] = null;
            }
        });
    }

    /**
     * 处理进度条
     *
     * @param serviceName
     * @param ability
     * @param longStub
     */
    public static void handlePregress(String serviceName, AbilitySlice ability, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IProgressIDL[] processIdl = new IProgressIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                processIdl[0] = ProgressIDLStub.asInterface(remote);
                try {
                    String ret = processIdl[0].getNumber(1);
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                processIdl[0] = null;
            }
        });
    }

    /**
     * 多进程更新进度条
     *
     * @param serviceName
     * @param ability
     * @param longStub
     */
    public static void handleProcess(String serviceName, AbilitySlice ability, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IProcessIDL[] processIdl = new IProcessIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                processIdl[0] = ProcessIDLStub.asInterface(remote);
                try {
                    String ret = processIdl[0].getNumber(1);
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                processIdl[0] = null;
            }
        });
    }

    /**
     * 第二个进程设置用户
     *
     * @param serviceName
     * @param ability
     * @param longStub
     */
    public static void handleUser(String serviceName, AbilitySlice ability, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IUserManagerIDL[] iuserIdl = new IUserManagerIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                iuserIdl[0] = UserManagerIDLStub.asInterface(remote);
                try {
                    String ret = iuserIdl[0].getUser(new UserManager());
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                iuserIdl[0] = null;
            }
        });
    }

    /**
     * 第三个进程设置用户
     *
     * @param serviceName
     * @param ability
     * @param longStub
     */
    public static void handleUserProcessThree(String serviceName, AbilitySlice ability, StubCallback longStub) {
        Intent intent = new Intent();
        startService(intent, serviceName, ability);
        IUserManagerProcessIDL[] iuserIdl = new IUserManagerProcessIDL[1];
        ability.connectAbility(intent, new IAbilityConnection() {
            @Override
            public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
                iuserIdl[0] = UserManagerProcessIDLStub.asInterface(remote);
                try {
                    String ret = iuserIdl[0].getUser(new UserManager());
                    if (longStub != null) {
                        longStub.result(ret);
                    }
                } catch (RemoteException e) {
                    HeLog.d(REMOTERROR);
                }
            }

            @Override
            public void onAbilityDisconnectDone(ElementName element, int resultCode) {
                iuserIdl[0] = null;
            }
        });
    }

    /**
     * 启动service
     *
     * @param intent
     * @param serviceName
     * @param ability
     */
    private static void startService(Intent intent, String serviceName, AbilitySlice ability) {
        if (ability == null) {
            return;
        }
        String bundleName = "";
        if (ability.getAbilityPackageContext() != null) {
            bundleName = ability.getAbilityPackageContext().getBundleName();
        } else {
            bundleName = AbilityDelegatorRegistry.getArguments().getTestBundleName();
        }

        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(bundleName)
                .withAbilityName(serviceName)
                .build();
        intent.setOperation(operation);
        ability.startAbility(intent, 0);
    }
}
